home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / zc / gunk.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  15KB  |  934 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    gunk.c
  12.  *
  13.  *    Transformations on expression trees
  14.  *    Most of this stuff is because we cant handle
  15.  *    floats, long mul/div, or fields directly.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "param.h"
  20. #include "bstok.h"
  21. #include "tytok.h"
  22. #include "flags.h"
  23. #include "nodes.h"
  24. #include "gen.h"
  25.  
  26. NODEP copyone();
  27.  
  28. #define gwiden(x)    ((x)==1 ? 2 : (x))
  29. #define isfield(np)    ((np)->g_token == '.' && (np)->g_fldw)
  30.  
  31. NODEP npar1, npar2, npar3;
  32. char *spar1, *spar2, *spar3;
  33. int ipar1, ipar2, ipar3;
  34.  
  35. struct rule {
  36.     int (*match)();        /* test for transformation needed */
  37.     int (*rewri)();        /* rewrite function */
  38. };
  39.  
  40. int m_unfold(), unfold(), m_cast(), cast(), m_inline(), inline();
  41. int m_hardas(), hardas(), m_fcmp(), fcmp(), m_md_shf(), md_shf();
  42. int m_eident(), eident(), m_incdec(), incdec(), m_fldas(), fldas();
  43.  
  44. struct rule gunktbl[] = {
  45.     {m_unfold, unfold},
  46.     {m_cast, cast},
  47.     {m_md_shf, md_shf},
  48.     {m_eident, eident},
  49.     {m_incdec, incdec},
  50.     {m_hardas, hardas},
  51.     {m_inline, inline}, /* must cast before inline */
  52.     {m_fcmp, fcmp},
  53.     {m_fldas, fldas},
  54.     {0}
  55. };
  56.  
  57. int anygunk;
  58.  
  59. gunk(np)
  60. NODEP np;
  61. {
  62.     do {
  63.         anygunk = 0;
  64.         gunks(np);
  65.     } while (anygunk);
  66. }
  67.  
  68. gunks(np)
  69. register NODEP np;
  70. {
  71.     switch (np->g_type) {
  72.     case E_BIN:
  73.         gunks(np->n_right);
  74.     case E_UNARY:
  75.         gunks(np->n_left);
  76.     }
  77.     gunk1(np);
  78. }
  79.  
  80. gunk1(np)
  81. NODEP np;
  82. {
  83.     register struct rule *p;
  84.  
  85.     for (p=gunktbl; p->match; p++)
  86.         if ((*p->match)(np)) {
  87.             anygunk++;
  88.             (*p->rewri)(np);
  89.             return;
  90.         }
  91. }
  92.  
  93. /*
  94.  *    Change pointer arithmetic to equivalent trees
  95.  *        (main thing is to mult or div by object size)
  96.  */
  97. m_unfold(np)
  98. NODEP np;
  99. {
  100.     switch (np->g_token) {
  101.     case PTRADD:
  102.         ipar1 = '+';
  103.         return 1;
  104.     case PTRSUB:
  105.         ipar1 = '-';
  106.         return 1;
  107.     case PTRDIFF:
  108.         ipar1 = 0;
  109.         return 1;
  110.     case ASSIGN PTRADD:
  111.         ipar1 = ASSIGN '+';
  112.         return 1;
  113.     case ASSIGN PTRSUB:
  114.         ipar1 = ASSIGN '-';
  115.         return 1;
  116.     }
  117.     return 0;
  118. }
  119.  
  120. unfold(np)
  121. NODEP np;
  122. {
  123.     if (ipar1) {
  124.         ins_mul(np, np->g_offs);
  125.         np->g_token = ipar1;
  126.     } else {
  127.         ins_div(np, np->g_offs);
  128.     }
  129. }
  130.  
  131. NODEP
  132. newgcon(kon, ty, sz)
  133. long kon;
  134. {
  135.     register NODEP kp;
  136.  
  137.     kp = allocnode();
  138.     kp->g_token = ICON;
  139.     sprintf(kp->n_name, "%ld", kon);
  140.     kp->g_offs = kon;
  141.     kp->g_type = E_LEAF;
  142.     kp->g_ty = ty;
  143.     kp->g_sz = sz;
  144.     return kp;
  145. }
  146.  
  147. ins_mul(np, kon)
  148. NODEP np;
  149. long kon;
  150. {
  151.     NODEP rp = np->n_right;
  152.     register NODEP mp, kp;
  153.  
  154.     if (kon == 1)
  155.         return;
  156.     if (rp->g_token == ICON) {
  157.         rp->g_offs *= kon;
  158.         rp->g_sz = gwiden(rp->g_sz);
  159.         return;
  160.     }
  161.  
  162.     mp = allocnode();
  163.     mp->g_token = '*';
  164.     sprintf(mp->n_name, "p*");
  165.     mp->g_type = E_BIN;
  166.     mp->g_ty = rp->g_ty;
  167.     mp->g_sz = gwiden(rp->g_sz);
  168.  
  169.     kp = newgcon(kon, mp->g_ty, mp->g_sz);
  170.  
  171.     mp->n_right = kp;
  172.     mp->n_left = np->n_right;
  173.     np->n_right = mp;
  174. }
  175.  
  176. ins_div(np, kon)
  177. register NODEP np;
  178. long kon;
  179. {
  180.     register NODEP tp, kp;
  181.  
  182.     kp = newgcon(kon, np->g_ty, np->g_sz);
  183.  
  184.     tp = copyone(np);
  185.     tp->g_token = '-';
  186.     tp->n_left = np->n_left;
  187.     tp->n_right = np->n_right;
  188.     tp->g_sz = SIZE_P;
  189.     tp->g_ty = ET_U;
  190.  
  191.     np->n_left = tp;
  192.     np->n_right = kp;
  193.     np->g_type = E_BIN;
  194.     np->g_token = '/';
  195.     sprintf(np->n_name, "p/");
  196. }
  197.  
  198. #define CAST_LN    1
  199. #define CAST_RN 2
  200. #define CAST_LLONG    3
  201.  
  202. /*
  203.  *    Insert needed (implied) casts
  204.  */
  205. m_cast(np)
  206. NODEP np;
  207. {
  208.     NODEP lp = np->n_left;
  209.  
  210.     switch (np->g_type) {
  211.     case E_LEAF:
  212.         return 0;
  213.     case E_BIN:
  214.         return bm_cast(np);
  215.     }
  216.     /* must be unary */
  217.     switch (np->g_token) {
  218.     case UNARY '-':
  219.     case '~':
  220.         return castup(lp, np, CAST_LN);
  221.     case TCONV:
  222.         return fcastlong(np);
  223.     }
  224.     return 0;
  225. }
  226.  
  227. bm_cast(np)
  228. register NODEP np;
  229. {
  230.     NODEP lp = np->n_left, rp = np->n_right;
  231.  
  232.     if (isassign(np->g_token)) {
  233.         if (castup(rp, lp, CAST_RN))
  234.             return 1;
  235.         if (castmagic(rp, lp, CAST_RN, np->g_token - (ASSIGN 0)))
  236.             return 1;
  237.         return 0;
  238.     }
  239.  
  240.     switch (np->g_token) {
  241.     case '=':
  242.         return castany(rp, lp, CAST_RN);
  243.  
  244.     case '<':
  245.     case '>':
  246.     case DOUBLE '=':
  247.     case NOTEQ:
  248.     case LTEQ:
  249.     case GTEQ:
  250.         if (castup(lp, rp, CAST_LN))
  251.             return 1;
  252.         return castup(rp, lp, CAST_RN);
  253.  
  254.     case '(':
  255.     case ',':
  256.     case '?':
  257.     case DOUBLE '&':
  258.     case DOUBLE '|':
  259.         return 0;
  260.  
  261.     case DOUBLE '<':
  262.     case DOUBLE '>':
  263.         if (castup(lp, np, CAST_LN))
  264.             return 1;
  265.         return castany(rp, np, CAST_RN);
  266.  
  267.     default:
  268.         if (castup(lp, np, CAST_LN))
  269.             return 1;
  270.         return castup(rp, np, CAST_RN);
  271.     }
  272.     return 0;
  273. }
  274.  
  275. fcastlong(np)
  276. NODEP np;
  277. {
  278.     NODEP lp = np->n_left;
  279.  
  280.     if (red_con(lp))
  281.         return 0;
  282.     if (np->g_ty == ET_F && lp->g_ty != ET_F && lp->g_sz != SIZE_L) {
  283.         ipar1 = CAST_LLONG;
  284.         return 1;
  285.     }
  286.     if (lp->g_ty == ET_F && np->g_ty != ET_F && np->g_sz != SIZE_L) {
  287.         ipar1 = CAST_LLONG;
  288.         return 1;
  289.     }
  290.     return 0;
  291. }
  292.  
  293. castup(lowp, hip, par)
  294. NODEP lowp, hip;
  295. {
  296.     if (stronger(hip, lowp)) {
  297.         ipar1 = par;
  298.         npar1 = hip;
  299.         return 1;
  300.     }
  301.     return 0;
  302. }
  303.  
  304. castmagic(p1, p2, par, tok)
  305. NODEP p1, p2;
  306. {
  307.     if (xstronger(p1,p2) && magicop(tok)) {
  308.         ipar1 = par;
  309.         npar1 = p2;
  310.         return 1;
  311.     }
  312.     return 0;
  313. }
  314.  
  315. castany(p1, p2, par)
  316. NODEP p1, p2;
  317. {
  318.     if (p1->g_sz != p2->g_sz ||
  319.         ((p1->g_ty == ET_F) != (p2->g_ty == ET_F))) {
  320.         ipar1 = par;
  321.         npar1 = p2;
  322.         return 1;
  323.     }
  324.     return 0;
  325. }
  326.  
  327. cast(np)
  328. NODEP np;
  329. {
  330.     switch (ipar1) {
  331.     case CAST_LN:
  332.         castsub(npar1->g_ty, npar1->g_sz, &np->n_left, np->n_left);
  333.         break;
  334.     case CAST_RN:
  335.         castsub(npar1->g_ty, npar1->g_sz, &np->n_right, np->n_right);
  336.         break;
  337.     case CAST_LLONG:
  338.         castsub(ET_S, SIZE_L, &np->n_left, np->n_left);
  339.         break;
  340.     }
  341. }
  342.  
  343. castsub(ty, sz, npp, np)
  344. NODEP *npp, np;
  345. {
  346.     register NODEP tp;
  347.  
  348.     /* ICON cast optimization */
  349.     if (np->g_token == ICON &&
  350.         np->g_ty == ty &&
  351.         np->g_sz < sz) {
  352.         np->g_sz = sz;
  353.         return;
  354.     }
  355.  
  356.     tp = allocnode();
  357.     tp->g_token = TCONV;
  358.     strcpy(tp->n_name, "cast up");
  359.     tp->n_left = np;
  360.     *npp = tp;
  361.     tp->g_sz = sz;
  362.     tp->g_ty = ty;
  363.     tp->g_type = E_UNARY;
  364. }
  365.  
  366. /*
  367.  *    Change stuff computer cant do to calls to inline functions
  368.  *    (in this case, all floats and long *%/)
  369.  */
  370. m_inline(np)
  371. NODEP np;
  372. {
  373.     int isfloat, isuns;
  374.  
  375.     if (np->g_type == E_LEAF)
  376.         return 0;
  377.  
  378.     isfloat = (np->g_ty == ET_F);
  379.     isuns = (np->g_ty == ET_U);
  380.  
  381.     if (np->g_type == E_UNARY) {
  382.         switch (np->g_token) {
  383.         case UNARY '-':
  384.             if (!isfloat) return 0;
  385.             spar1 = "%fpneg";
  386.             return 1;
  387.         case TCONV:
  388.             if ((np->n_left->g_ty == ET_F) == isfloat)
  389.                 return 0;
  390.             if (red_con(np->n_left))
  391.                 return 0;
  392.             spar1 = isfloat ? "fpltof" : "fpftol";
  393.             return 1;
  394.         }
  395.         return 0;
  396.     }
  397.  
  398.     if (np->g_sz != 4)    /* longs or floats only */
  399.         return 0;
  400.  
  401.     switch (np->g_token) {
  402.     case '*':
  403.         spar1 = isfloat ? "%fpmul" : (isuns ? "%lmulu" : "%lmul");
  404.         return 1;
  405.     case '/':
  406.         spar1 = isfloat ? "%fpdiv" : (isuns ? "%ldivu" : "%ldiv");
  407.         return 1;
  408.     case '+':
  409.         if (!isfloat) return 0;
  410.         spar1 = "%fpadd";
  411.         return 1;
  412.     case '-':
  413.         if (!isfloat) return 0;
  414.         spar1 = "%fpsub";
  415.         return 1;
  416.     case '%':
  417.         spar1 = isuns ? "%lremu" : "%lrem";
  418.         return 1;
  419.     }
  420.     return 0;
  421. }
  422.  
  423. inline(np)
  424. NODEP np;
  425. {
  426.     register NODEP nmp, cmap;
  427.     int isunary;
  428.  
  429.     isunary = (np->g_type == E_UNARY);
  430.  
  431.     if (isunary) {
  432.         np->n_right = np->n_left;
  433.         np->g_type = E_BIN;
  434.     } else {
  435.         cmap = copyone(np);
  436.         cmap->n_left = np->n_left;
  437.         cmap->n_right = np->n_right;
  438.         np->n_right = cmap;
  439.  
  440.         cmap->g_token = ',';
  441.         cmap->g_offs = 2;
  442.         strcpy(cmap->n_name, ",inl");
  443.     }
  444.  
  445.     nmp = allocnode();
  446.     np->n_left = nmp;
  447.  
  448.     np->g_token = '(';
  449.     strcpy(np->n_name, "inline");
  450.  
  451.     nmp->g_token = ID;
  452.     strcpy(nmp->n_name, spar1);
  453. }
  454.  
  455. /*
  456.  *    Transform hard ++,-- to equivalent trees
  457.  *    (for us, floats or fields)
  458.  */
  459. m_incdec(np)
  460. NODEP np;
  461. {
  462.     if (np->g_type != E_UNARY)
  463.         return 0;
  464.     if (np->g_ty != ET_F && !isfield(np->n_left))
  465.         return 0;
  466.  
  467.     ipar2 = 0;
  468.     switch (np->g_token) {
  469.     case DOUBLE '+':
  470.         ipar1 = ASSIGN '+';
  471.         spar1 = "+=";
  472.         break;
  473.     case DOUBLE '-':
  474.         ipar1 = ASSIGN '-';
  475.         spar1 = "-=";
  476.         break;
  477.     case POSTINC:
  478.         ipar1 = DOUBLE '+';
  479.         spar1 = "++";
  480.         ipar2 = '-';
  481.         spar2 = "-";
  482.         break;
  483.     case POSTDEC:
  484.         ipar1 = DOUBLE '-';
  485.         spar1 = "--";
  486.         ipar2 = '+';
  487.         spar2 = "+";
  488.         break;
  489.     default:
  490.         return 0;
  491.     }
  492.     return 1;
  493. }
  494.  
  495. incdec(np)
  496. register NODEP np;
  497. {
  498.     NODEP t1;
  499.     NODEP onep;
  500.  
  501.     onep = newgcon(1L, ET_S, SIZE_I);
  502.  
  503.     if (ipar2 == 0) {        /* easy case, ++X becomes X+=1 */
  504.         np->g_token = ipar1;
  505.         np->g_type = E_BIN;
  506.         np->n_right = onep;
  507.         strcpy(np->n_name, spar1);
  508.         return;
  509.     }
  510.  
  511.     /* hard case, X++ becomes (++X - 1) */
  512.     t1 = copyone(np);
  513.     t1->n_left = np->n_left;
  514.     np->n_left = t1;
  515.     np->n_right = onep;
  516.     np->g_type = E_BIN;
  517.     np->g_token = ipar2;
  518.     strcpy(np->n_name, spar2);
  519.  
  520.     t1->g_token = ipar1;
  521.     strcpy(t1->n_name, spar1);
  522. }
  523.  
  524. /*
  525.  *    Transform hard op= trees to equivalent '=' trees
  526.  *    (in this case, all floats, long or char *%/, fields)
  527.  */
  528. m_hardas(np)
  529. NODEP np;
  530. {
  531.     int op;
  532.  
  533.     if (np->g_type != E_BIN)
  534.         return 0;
  535.     op = np->g_token;
  536.     if (isassign(op))
  537.         op -= ASSIGN 0;
  538.     else
  539.         return 0;
  540.     if (xstronger(np->n_right, np->n_left) &&
  541.         magicop(op) == 0)
  542.         return 1;
  543.     if (np->g_ty == ET_F || isfield(np->n_left))
  544.         return 1;
  545.     if (np->g_sz == 4 || np->g_sz == 1)
  546.         switch (op) {
  547.         case '*':
  548.         case '/':
  549.         case '%':
  550.             return 1;
  551.         }
  552.     return 0;
  553. }
  554.  
  555. hardas(np)
  556. NODEP np;
  557. {
  558.     NODEP opp, newl;
  559.     NODEP copynode();
  560.  
  561.     if (m_vhard(np)) {
  562.         vhard(np);
  563.         return;
  564.     }
  565.  
  566.     opp = copyone(np);
  567.     newl = copynode(np->n_left);
  568.     opp->n_right = np->n_right;
  569.     np->n_right = opp;
  570.     opp->n_left = newl;
  571.  
  572.     np->g_token = '=';
  573.     strcpy(np->n_name, "unfold");
  574.  
  575.     opp->g_token -= (ASSIGN 0);
  576.     bmaxty(opp);
  577. }
  578.  
  579. /*
  580.  *    Check for lhs of op= that have side effects or are complex
  581.  */
  582. m_vhard(np)
  583. NODEP np;
  584. {
  585.     NODEP lp = np->n_left;
  586.  
  587.     while (lp->g_token == '.')
  588.         lp = lp->n_left;
  589.     if (lp->g_token != STAR)
  590.         return 0;
  591.     return isvhard(lp->n_left);
  592. }
  593.  
  594. isvhard(np)
  595. NODEP np;
  596. {
  597.     NODEP rp;
  598.  
  599. descend:
  600.     switch (np->g_type) {
  601.     case E_LEAF:
  602.         return 0;
  603.     case E_UNARY:
  604.         switch (np->g_token) {
  605.         case '(':
  606.         case DOUBLE '+':
  607.         case DOUBLE '-':
  608.         case POSTINC:
  609.         case POSTDEC:
  610.             return 1;
  611.         default:
  612.             np = np->n_left;
  613.             goto descend;
  614.         }
  615.     case E_BIN:
  616.         switch (np->g_token) {
  617.         case '+':
  618.         case '-':
  619.             rp = np->n_right;
  620.             if (rp->g_token == ICON && np->g_ty != ET_F) {
  621.                 np = np->n_left;
  622.                 goto descend;
  623.             }
  624.             /* fall through */
  625.         default:
  626.             return 1;
  627.         }
  628.     }
  629. }
  630.  
  631. vhard(np)
  632. NODEP np;
  633. {
  634.     NODEP starp;
  635.     NODEP atree, btree;
  636.     NODEP t1, t2;
  637.     register NODEP opp;
  638.     NODEP tmp_var();
  639.  
  640.     starp = np->n_left;
  641.     while (starp->g_token == '.')
  642.         starp = starp->n_left;
  643.     atree = starp->n_left;
  644.     btree = np->n_right;
  645.     t1 = tmp_var(ET_U, SIZE_P);
  646.     t2 = copyone(t1);
  647.     starp->n_left = t2;
  648.  
  649.     opp = copyone(t1);
  650.     opp->g_type = E_BIN;
  651.     opp->g_token = '=';
  652.     strcpy(opp->n_name, "=");
  653.     opp->n_right = atree;
  654.     opp->n_left = t1;
  655.  
  656.     comma_r(np, opp);
  657. }
  658.  
  659. comma_r(topp, lp)
  660. NODEP topp, lp;
  661. {
  662.     register NODEP newp;
  663.  
  664.     newp = copyone(topp);
  665.     topp->g_token = ',';
  666.     strcpy(topp->n_name, ",");
  667.     newp->n_left = topp->n_left;
  668.     newp->n_right = topp->n_right;
  669.     topp->n_left = lp;
  670.     topp->n_right = newp;
  671. }
  672.  
  673. NODEP
  674. tmp_var(ty, sz)
  675. {
  676.     register NODEP t1;
  677.  
  678.     t1 = allocnode();
  679.     t1->g_token = OREG;
  680.     t1->g_type = E_LEAF;
  681.     t1->g_rno = AREG+6;
  682.     t1->g_ty = ty;
  683.     t1->g_sz = sz;
  684.     t1->g_offs = - tmp_alloc(sz);
  685.     strcpy(t1->n_name, "tmp_v");
  686.     return t1;
  687. }
  688.  
  689. /* X op= Y where Y's type is stronger than X's
  690.     either unfold it or (default)
  691.     cast Y to weaker type (+ or -)
  692. */
  693.  
  694. magicop(op)
  695. {
  696.     switch (op) {
  697.     case '+':
  698.     case '-':
  699.     case DOUBLE '<':
  700.     case DOUBLE '>':
  701.     case '&':
  702.     case '|':
  703.     case '^':
  704.         return 1;
  705.     }
  706.     return 0;
  707. }
  708.  
  709. stronger(xp, yp)
  710. NODEP xp, yp;
  711. {
  712.     if (xp->g_sz > yp->g_sz || 
  713.         (xp->g_sz == yp->g_sz && xp->g_ty > yp->g_ty))
  714.         return 1;
  715.     return 0;
  716. }
  717.  
  718. /* stronger with ET_S and ET_U considered equal */
  719. xstronger(xp, yp)
  720. NODEP xp, yp;
  721. {
  722.     if (xp->g_sz > yp->g_sz ||
  723.         (xp->g_ty == ET_F && yp->g_ty != ET_F))
  724.         return 1;
  725.     return 0;
  726. }
  727.  
  728. /* give np the type of the stronger child */
  729. bmaxty(np)
  730. NODEP np;
  731. {
  732.     NODEP lp = np->n_left, rp = np->n_right;
  733.  
  734.     if (stronger(lp, rp))
  735.         rp = lp;
  736.     np->g_ty = rp->g_ty;
  737.     np->g_sz = gwiden(rp->g_sz);
  738. }
  739.  
  740. /*
  741.  *    Change floating compares to inline call 
  742.  */
  743. m_fcmp(np)
  744. NODEP np;
  745. {
  746.         /* already made L and R same with casts */
  747.     if (np->g_type != E_BIN || np->n_left->g_ty != ET_F)
  748.         return 0;
  749.     switch (np->g_token) {
  750.     case '<':
  751.         spar2 = "lt";
  752.         return 1;
  753.     case '>':
  754.         spar2 = "gt";
  755.         return 1;
  756.     case DOUBLE '=':
  757.         spar2 = "eq";
  758.         return 1;
  759.     case NOTEQ:
  760.         spar2 = "ne";
  761.         return 1;
  762.     case GTEQ:
  763.         spar2 = "ge";
  764.         return 1;
  765.     case LTEQ:
  766.         spar2 = "le";
  767.         return 1;
  768.     }
  769.     return 0;
  770. }
  771.  
  772. fcmp(np)
  773. register NODEP np;
  774. {
  775.     register NODEP tp;
  776.  
  777.     spar1 = "%fpcmp";
  778.     inline(np);
  779.  
  780.     tp = copyone(np);
  781.     tp->n_left = np->n_left;
  782.     tp->n_right = np->n_right;
  783.     np->n_left = tp;
  784.  
  785.     np->n_right = NULL;
  786.     np->g_type = E_UNARY;
  787.     np->g_token = CMPBR;
  788.     sprintf(np->n_name, spar2);
  789. }
  790.  
  791. /*
  792.  *    Remove useless binary operations with identity constant
  793.  */
  794. m_eident(np)
  795. NODEP np;
  796. {
  797.     NODEP rp = np->n_right;
  798.     long l;
  799.     int i, op;
  800.  
  801.     if (np->g_type != E_BIN)
  802.         return 0;
  803.     if (np->g_ty == ET_F)
  804.         return 0;
  805.     while (rp->g_token == TCONV && rp->g_ty != ET_F)
  806.         rp = rp->n_left;
  807.     if (rp->g_token != ICON)
  808.         return 0;
  809.     l = rp->g_offs;
  810.     if (l < 0 || l > 1)
  811.         return 0;
  812.  
  813.     op = np->g_token;
  814.     if (isassign(op))
  815.         op -= ASSIGN 0;
  816.     switch (op) {
  817.     case '+':
  818.     case '-':
  819.     case DOUBLE '<':
  820.     case DOUBLE '>':
  821.     case '|':
  822.     case '^':
  823.         i = 0;    break;
  824.     case '*':
  825.     case '/':
  826.         i = 1;  break;
  827.     default:
  828.         return 0;
  829.     }
  830.     if (l != i)
  831.         return 0;
  832.     return 1;    
  833. }
  834.  
  835. eident(np)
  836. NODEP np;
  837. {
  838.     NODEP lp = np->n_left, rp = np->n_right;
  839.  
  840.     freenode(rp);
  841.     
  842.     lcpy(np, lp, sizeof(NODE)/4);
  843.  
  844.     freeunit(lp);
  845. }
  846.  
  847. #define MAXLOOK    8
  848.  
  849. /*
  850.  *    Change certain mult or div to equivalent shift
  851.  */
  852. m_md_shf(np)
  853. NODEP np;
  854. {
  855.     NODEP rp = np->n_right;
  856.     long l;
  857.     register i, j;
  858.  
  859.     if (np->g_type != E_BIN)
  860.         return 0;
  861.     if (np->g_ty == ET_F)
  862.         return 0;
  863.     while (rp->g_token == TCONV && rp->g_ty != ET_F)
  864.         rp = rp->n_left;
  865.     if (rp->g_token != ICON)
  866.         return 0;
  867.  
  868.     switch (np->g_token) {
  869.     case '*':
  870.         ipar1 = DOUBLE '<';  break;
  871.     case '/':
  872.         ipar1 = DOUBLE '>';  break;
  873.     case ASSIGN '*':
  874.         ipar1 = ASSIGN DOUBLE '<';  break;
  875.     case ASSIGN '/':
  876.         ipar1 = ASSIGN DOUBLE '>';  break;
  877.     default:
  878.         return 0;
  879.     }
  880.  
  881.     l = rp->g_offs;
  882.     if (l < 2 || l > (1<<MAXLOOK))
  883.         return 0;
  884.     i = l;
  885.     for (j=1; j<=MAXLOOK; j++)
  886.         if (i == 1<<j) {
  887.             ipar2 = j;
  888.             return 1;
  889.         }
  890.     return 0;
  891. }
  892.  
  893. md_shf(np)
  894. NODEP np;
  895. {
  896.     NODEP rp = np->n_right;
  897.  
  898.     np->g_token = ipar1;
  899.     while (rp->g_token == TCONV)
  900.         rp = rp->n_left;
  901.     rp->g_offs = ipar2;
  902. }
  903.  
  904. m_fldas(np)
  905. NODEP np;
  906. {
  907.     if (np->g_type != E_BIN)
  908.         return 0;
  909.     if (np->g_token == '=' && isfield(np->n_left))
  910.         return 1;
  911. }
  912.  
  913. fldas(np)
  914. register NODEP np;
  915. {
  916.     NODEP lp = np->n_left;
  917.  
  918.     np->g_fldw = lp->g_fldw;
  919.     np->g_fldo = lp->g_fldo;
  920.     np->g_token = FIELDAS;
  921.  
  922.     lp->g_fldw = 0;
  923. }
  924.  
  925. red_con(np)
  926. register NODEP np;
  927. {
  928.     while (np->g_token == TCONV)
  929.         np = np->n_left;
  930.     if (np->g_token == ICON || np->g_token == FCON)
  931.         return 1;
  932.     return 0;
  933. }
  934.